﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#region using for special implements
using Com.ProjectA.DAO;
using Com.ProjectA.DAC;
using Com.ProjectA.Utility;
#endregion using for special implements

namespace Com.ProjectA.BusinessLogic
{
    public class BLPersonManager
    {
        #region Declare variables
        #region Declare sql query
        private const string STR_INSERT_PERSON = @"insert into tb_fa_person 
                                                                        (person_code, first_name, middle_name
                                                                        , last_name, birthday, death_day
                                                                        , number_children, sex, biography_id
                                                                        , born_id, create_uid, update_uid
                                                                        , person_status)
                                                                        values('{person_code}','{first_name}','{middle_name}'
                                                                        ,'{last_name}', '{birthday}', '{death_day}'
                                                                        , {number_children}, '{sex}', {biography_id}
                                                                        , {born_id}, {create_uid}, {update_uid}, '{person_status}')";
        private const string STR_UPDATE_PERSON = @"update tb_fa_person set first_name = '{first_name}', middle_name = '{middle_name}', last_name = '{last_name}'
                                                                        , birthday = '{birthday}', death_day = '{death_day}'
                                                                        , number_children = {number_children}, sex = '{sex}'
                                                                        , biography_id = {biography_id}, born_id = {born_id}
                                                                        , create_uid = {create_uid}, update_uid = {update_uid}
                                                                        , person_status = '{person_status}' where person_id = {person_id}";
        private const string STR_LIST_PERSON = @"select person_id, person_code, first_name, middle_name, last_name
                                                        , birthday, death_day, number_children, sex, biography_id, born_id
                                                        , create_uid, update_uid, person_status
                                                from tb_fa_person
                                                where person_status = 'Y'";
        private const string STR_DETAIL_PERSON = @"select person_id, person_code, first_name, middle_name, last_name
                                                        , birthday, death_day, number_children, sex, biography_id, born_id
                                                        , create_uid, update_uid, person_status
                                                from tb_fa_person
                                                where
                                                    person_id = {person_id}
                                                    and person_status = 'Y'";
        #region Get Max
        private const string STR_GET_MAX_DESCENDENT_CODE_BY_CUR_CODE = @"select Max(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 2, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                        person_code like '{person_code}%' 
                                                                        and LEN(person_code) = LEN('{person_code}') + 6";

        private const string STR_GET_MAX_SIBLING_CODE_BY_CUR_CODE = @"select Max(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 2, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                            LEN(person_code) = LEN('{person_code}')
                                                                        and SUBSTRING(person_code, 0, len(person_code) - 5) = SUBSTRING('{person_code}', 0, len('{person_code}') - 5)";
        private const string STR_GET_MAX_DESCENDENT_MOM_CODE_BY_CUR_CODE = @"select Max(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 5, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                        person_code like '{person_code}%' 
                                                                        and LEN(person_code) = LEN('{person_code}') + 6";

        private const string STR_GET_MAX_SIBLING_MOM_CODE_BY_CUR_CODE = @"select Max(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 5, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                            LEN(person_code) = LEN('{person_code}')
                                                                        and SUBSTRING(person_code, 0, len(person_code) - 5) = SUBSTRING('{person_code}', 0, len('{person_code}') - 5)";
        #endregion Get Max
        #region Get Min
        private const string STR_GET_MIN_DESCENDENT_CODE_BY_CUR_CODE = @"select MIN(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 2, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                        person_code like '{person_code}%' 
                                                                        and LEN(person_code) = LEN('{person_code}') + 6";

        private const string STR_GET_MIN_SIBLING_CODE_BY_CUR_CODE = @"select MIN(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 2, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                            LEN(person_code) = LEN('{person_code}')
                                                                        and SUBSTRING(person_code, 0, len(person_code) - 5) = SUBSTRING('{person_code}', 0, len('{person_code}') - 5)";
        private const string STR_GET_MIN_DESCENDENT_MOM_CODE_BY_CUR_CODE = @"select MIN(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 5, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                        person_code like '{person_code}%' 
                                                                        and LEN(person_code) = LEN('{person_code}') + 6";

        private const string STR_GET_MIN_SIBLING_MOM_CODE_BY_CUR_CODE = @"select MIN(CONVERT(INT,SUBSTRING(person_code, len(person_code) - 5, 3)))
                                                                        from tb_fa_person
                                                                        where 
                                                                            LEN(person_code) = LEN('{person_code}')
                                                                        and SUBSTRING(person_code, 0, len(person_code) - 5) = SUBSTRING('{person_code}', 0, len('{person_code}') - 5)";
        #endregion Get Min
        private const string STR_GET_SEACH_PERSON = @"select person_code,first_name,middle_name,last_name,birthday,death_day" +
                                                   " from tb_fa_person " +
                                                   " where person_code like N'%{person_code}%'"+
                                                    " and first_name like N'%{first_name}%' "+
                                                    " and middle_name like N'%{middle_name}%'"+
                                                    " and last_name like N'%{last_name}%' "+
                                                    " and birthday like '%{birthday}%'"+
                                                    " and death_day like '%{death_day}%'";
        private const string STR_DETAIL_PERSON_BY_CODE = @"select person_id, person_code, first_name, middle_name, last_name
                                                        , birthday, death_day, number_children, sex,biography_id,born_id,create_uid ,update_uid,person_status 
                                                        from tb_fa_person
                                                        where  person_code = '{person_code}'";

        private const string STR_CALL_PERSON = @" select master_data_id  ,master_data_key,master_data_code,master_data_type_1,master_data_type_2,master_data_type_3 ,master_data_name
                                                  ,master_data_value_num
                                                  ,master_data_value_datetime
                                                  ,master_data_value_string
                                                  ,master_data_description
                                                  ,create_date
                                                  ,create_uid
                                                  ,update_date
                                                  ,update_uid
                                                  ,master_data_status
                                                 FROM tb_fa_master_data
                                                 where master_data_type_1='{master_data_type_1}'
                                                   and master_data_type_2='{master_data_type_2}'
                                                   and master_data_type_3={master_data_type_3}";



        #endregion Declare sql query
        private DACConnectionManager dacConnMgr = null;
        #endregion Declare variables
        /// <summary>
        /// BL Person Manager Constructure
        /// </summary>
        /// <param name="strConnectionName">Connection Name Of Connection String Was Defined In Web Config</param>
        /// <param name="isTran">Flag to recognize whether transaction is turn on or turn off</param>
        public BLPersonManager(string strConnectionName, bool isTran = false)
        {
            dacConnMgr = new DACConnectionManager(strConnectionName, isTran);
        }
        /// <summary>
        /// Create A Person
        /// </summary>
        /// <param name="daoPerson">Dao Person</param>
        /// <returns>message string</returns>
        public string CreatePerson(DAOPerson daoPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                int intResult = dacCmdMgr.ExecuteNonQueryCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, STR_INSERT_PERSON);
                return intResult == 1 ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person", "was created successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Person", "was created unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        /// <summary>
        /// Modify A Person
        /// </summary>
        /// <param name="daoPerson">Dao Person</param>
        /// <returns>message string</returns>
        public string ModifyPerson(DAOPerson daoPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            int intResult = 0;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                if (daoPerson.person_id == 0)
                {
                    intResult = dacCmdMgr.ExecuteNonQueryCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, STR_INSERT_PERSON);
                }
                else
                {
                    intResult = dacCmdMgr.ExecuteNonQueryCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, STR_UPDATE_PERSON);
                }
                return intResult == 1 ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person", "was modified successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Person", "was modified unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        /// <summary>
        /// List Person
        /// </summary>
        /// <returns>message string</returns>
        public string ListPerson(out List<DAOPerson> lsPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                lsPerson = dacCmdMgr.ExecuteReaderCommand<DAOPerson>(dacConnMgr, System.Data.CommandType.Text, STR_LIST_PERSON);

                return (lsPerson != null && lsPerson.Count > 0) ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Listing person", "is successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Listing person", "is unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                lsPerson = null;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        /// <summary>
        /// List Person
        /// </summary>
        /// <param name="intPerId">input Person Id</param>
        /// <param name="daoPerson">out DaoPerson</param>
        /// <returns>message string</returns>
        public string DetailPerson(int intPerId, out DAOPerson daoPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = dacCmdMgr.ExecuteReaderCommand<DAOPerson>(new DAOPerson(){person_id = intPerId}, dacConnMgr, System.Data.CommandType.Text, STR_DETAIL_PERSON);
                return (daoPerson != null && daoPerson.person_id > 0) ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Info", "is got successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Person Info", "is got unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                daoPerson = new DAOPerson();
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        /// <summary>
        /// DetailPerson
        /// </summary>
        /// <param name="intPerId">input PersonCode</param>
        /// <param name="daoPerson">out DaoPerson</param>
        /// <returns>message string</returns>
        public string DetailPerson(string Personcode, out DAOPerson daoPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = dacCmdMgr.ExecuteReaderCommand<DAOPerson>(new DAOPerson() { person_code = Personcode }, dacConnMgr, System.Data.CommandType.Text, STR_DETAIL_PERSON_BY_CODE);
                return (daoPerson != null && daoPerson.person_id > 0) ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Info", "is got successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Person Info", "is got unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                daoPerson = new DAOPerson();
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        /// <summary>
        /// Seach person tb_fa_person
        /// <param name="Person_code">input Person_code</param>
        /// <param name="first_name">input first_name</param>
        /// <param name="middle_name">input middle_name</param>
        /// <param name="last_name">input last_name</param>
        /// <param name="birthday">input birthday</param>
        /// <param name="Death_day">input Death_day</param>
        /// <param name="DaoPerson">out DaoPerson</param>
        /// </summary>
        public string SearchPerson(string Person_code,string first_name,string middle_name,string last_name,string birthday,string death_day,out List<DAOPerson> lsPerson)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
               
                string strCMD = STR_GET_SEACH_PERSON.Replace("{person_code}",Person_code.ToString());                
                strCMD=strCMD.Replace("{first_name}",first_name.ToString());
                strCMD = strCMD.Replace("{middle_name}", middle_name.ToString());
                strCMD = strCMD.Replace("{last_name}", last_name.ToString());
                strCMD = strCMD.Replace("{birthday}", birthday.ToString());
                strCMD = strCMD.Replace("{death_day}", death_day.ToString());
                lsPerson = dacCmdMgr.ExecuteReaderCommand<DAOPerson>(dacConnMgr, System.Data.CommandType.Text,strCMD);

                return (lsPerson != null && lsPerson.Count > 0) ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Listing search person", "is successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Listing search person", "is unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                lsPerson = null;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        public string CallPerson(string Master_data_type_1, string Master_data_type_2, float Master_data_type_3,out List<DAOMasterData> MasterData)
        {
            #region Declare variables
            DACCommandManager dacCmdMgr = null;
            #endregion Declare varibles
            try
            {
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                string strCMD = STR_CALL_PERSON.Replace("{master_data_type_1}",Master_data_type_1.ToString());
                strCMD = strCMD.Replace("{master_data_type_2}",Master_data_type_2.ToString());
                strCMD = strCMD.Replace("{master_data_type_3}", Master_data_type_3.ToString());

                MasterData = dacCmdMgr.ExecuteReaderCommand<DAOMasterData>(dacConnMgr, System.Data.CommandType.Text, strCMD);
                return (MasterData != null && MasterData.Count> 0) ? BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Call Person Info", "is got successfully")
                    : BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, " Call Person  Info", "is got unsuccessfully");
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                MasterData = null;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Call Person", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        #region THEM MEMBER VAO GIA PHA
        #region GET MAX, MIN MOM
        /// <summary>
        /// Get Max Mom Code By Person Code
        /// </summary>
        /// <param name="strPerCd">Input Person Code</param>
        /// <param name="intMaxMomCd">Output Maximum Mom Code - Integer type</param>
        /// <param name="isSibling">Flag to recognize that get sibling mom code or descendent code. True is getting maximum sibling mode code</param>
        /// <param name="lsPerson">List of dao person will be used to LINQ instead of sql query in db</param>
        /// <returns>Message Notification String</returns>
        public string GetMaxMomCdByPerCd(string strPerCd, out int intMaxMomCd, bool isSibling, List<DAOPerson> lsPerson = null)
        {
            #region Khai bao bien local
            DACCommandManager dacCmdMgr = null;
            string strMsg = null;
            DAOPerson daoPerson = null;
            IEnumerable<DAOPerson> lsPerTemp = null;
            string strSqlQuery = null;
            #endregion Khai bao bien local
            try
            {
                #region Validation
                // Neu person code la 01 thi se khong co sibling
                if (strPerCd.Equals("01") && isSibling)
                {
                    intMaxMomCd = -1;
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Mom Code By Person Code: ", "Can not get maximum mother code of root father"); 
                }
                #endregion Validation
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = new DAOPerson() { person_code = strPerCd };
                if (lsPerson == null)
                {
                    if (isSibling)
                    {
                        strSqlQuery = STR_GET_MAX_SIBLING_MOM_CODE_BY_CUR_CODE;
                    }
                    else
                    {
                        strSqlQuery = STR_GET_MAX_DESCENDENT_MOM_CODE_BY_CUR_CODE;
                    }
                    strMsg = dacCmdMgr.ExecuteScalarCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, out intMaxMomCd, strSqlQuery);
                }
                else
                {
                    if (isSibling)
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(BLGenealogic.GetXFatherCdOfPersonCd(strPerCd, BLGenealogic.FindGenRankOfPerCd(strPerCd) - 1))).ToList();
                    }
                    else
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(strPerCd));
                    }
                    if (lsPerTemp != null)
                    {
                        intMaxMomCd = lsPerTemp.Max(y => Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(y.person_code)));
                    }
                    else
                    {
                        intMaxMomCd = 0;
                    }
                    strMsg = "Successful";
                }
                if (intMaxMomCd == -1)
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Mom Code By Person Code: ", strMsg);
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Manager - Get Max Mom Code By Person Code: ", strMsg);
            }
            catch (Exception ex)
            {
                intMaxMomCd =-1;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Mom Code By Person Code: ", ex.Message);
            }
        }
        /// <summary>
        /// Get minimum mom code by person code
        /// </summary>
        /// <param name="strPerCd">Input person code</param>
        /// <param name="intMinMomCd">Output minimum mom code - Integer type</param>
        /// <param name="isSibling">Flag to recognize that get sibling mom code or descendent code. True is getting maximum sibling mode code</param>
        /// <param name="lsPerson">List of dao person will be used to LINQ instead of sql query in db</param>
        /// <returns>Message notification string</returns>
        public string GetMinMomCdByPerCd(string strPerCd, out int intMinMomCd, bool isSibling, List<DAOPerson> lsPerson = null)
        {
            #region Khai bao bien local
            DACCommandManager dacCmdMgr = null;
            string strMsg = null;
            DAOPerson daoPerson = null;
            IEnumerable<DAOPerson> lsPerTemp = null;
            string strSqlQuery = null;
            #endregion Khai bao bien local
            try
            {
                #region Validation
                // Neu person code la 01 thi se khong co sibling
                if (strPerCd.Equals("01") && isSibling)
                {
                    intMinMomCd = -1;
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Min Mom Code By Person Code: ", "Can not get minimum mother code of root father");
                }
                #endregion Validation
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = new DAOPerson() { person_code = strPerCd };
                if (lsPerson == null)
                {
                    if (isSibling)
                    {
                        strSqlQuery = STR_GET_MIN_SIBLING_MOM_CODE_BY_CUR_CODE;
                    }
                    else
                    {
                        strSqlQuery = STR_GET_MIN_DESCENDENT_MOM_CODE_BY_CUR_CODE;
                    }
                    strMsg = dacCmdMgr.ExecuteScalarCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, out intMinMomCd, strSqlQuery);
                }
                else
                {
                    if (isSibling)
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(BLGenealogic.GetXFatherCdOfPersonCd(strPerCd, BLGenealogic.FindGenRankOfPerCd(strPerCd) - 1))).ToList();
                    }
                    else
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(strPerCd)).ToList();
                    }
                    if (lsPerTemp != null)
                    {
                        intMinMomCd = lsPerTemp.Min(y => Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(y.person_code)));
                    }
                    else
                    {
                        intMinMomCd = 0;
                    }
                    strMsg = "Successful";
                }
                if (intMinMomCd == -1)
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Min Mom Code By Person Code: ", strMsg);
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Manager - Get Min Mom Code By Person Code: ", strMsg);
            }
            catch (Exception ex)
            {
                intMinMomCd = -1;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Min Mom Code By Person Code: ", ex.Message);
            }
        }
        #endregion GET MAX, MIN MOM
        #region GET MAX BROTHER(SIBLING)
        /// <summary>
        /// Get Max Brother Code By Person Code
        /// </summary>
        /// <param name="strPerCd">Input Person Code</param>
        /// <param name="intMaxBroCd">Output Maximum Brother Code - Integer type</param>
        /// <param name="isSibling">Flag to recognize that get sibling brother code or descendent code. True is getting maximum sibling brother code</param>
        /// <param name="lsPerson">List of dao person will be used to LINQ instead of sql query in db</param>
        /// <returns>Message Notification String</returns>
        public string GetMaxBroCdByPerCd(string strPerCd, out int intMaxBroCd, bool isSibling, List<DAOPerson> lsPerson = null)
        {
            #region Khai bao bien local
            DACCommandManager dacCmdMgr = null;
            string strMsg = null;
            DAOPerson daoPerson = null;
            IEnumerable<DAOPerson> lsPerTemp = null;
            string strSqlQuery = null;
            #endregion Khai bao bien local
            try
            {
                #region Validation
                // Neu person code la 01 thi se khong co sibling
                if (strPerCd.Equals("01") && isSibling)
                {
                    intMaxBroCd = -1;
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Brother Code By Person Code: ", "Can not get maximum brother code of root father");
                }
                #endregion Validation
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = new DAOPerson() { person_code = strPerCd };
                if (lsPerson == null)
                {
                    if (isSibling)
                    {
                        strSqlQuery = STR_GET_MAX_SIBLING_CODE_BY_CUR_CODE;
                    }
                    else
                    {
                        strSqlQuery = STR_GET_MAX_DESCENDENT_CODE_BY_CUR_CODE;
                    }
                    strMsg = dacCmdMgr.ExecuteScalarCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, out intMaxBroCd, strSqlQuery);
                }
                else
                {
                    if (isSibling)
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(BLGenealogic.GetXFatherCdOfPersonCd(strPerCd, BLGenealogic.FindGenRankOfPerCd(strPerCd) - 1))).ToList();
                    }
                    else
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(strPerCd)).ToList();
                    }
                    if (lsPerTemp != null)
                    {
                        intMaxBroCd = lsPerTemp.Max(y => Convert.ToInt32(y.person_code.Substring(y.person_code.Length - 4)));
                    }
                    else
                    {
                        intMaxBroCd = 0;
                    }
                    strMsg = "Successful";
                }
                if (intMaxBroCd == -1)
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Brother Code By Person Code: ", strMsg);
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Manager - Get Max Brother Code By Person Code: ", strMsg);
            }
            catch (Exception ex)
            {
                intMaxBroCd = -1;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Max Brother Code By Person Code: ", ex.Message);
            }
        }
        /// <summary>
        /// Get minimum brother code by person code
        /// </summary>
        /// <param name="strPerCd">Input person code</param>
        /// <param name="intMinBroCd">Output minimum brother code - Integer type</param>
        /// <param name="isSibling">Flag to recognize that get sibling brother code or descendent code. True is getting maximum sibling brother code</param>
        /// <param name="lsPerson">List of dao person will be used to LINQ instead of sql query in db</param>
        /// <returns>Message notification string</returns>
        public string GetMinBroCdByPerCd(string strPerCd, out int intMinBroCd, bool isSibling, List<DAOPerson> lsPerson = null)
        {
            #region Khai bao bien local
            DACCommandManager dacCmdMgr = null;
            string strMsg = null;
            DAOPerson daoPerson = null;
            IEnumerable<DAOPerson> lsPerTemp = null;
            string strSqlQuery = null;
            #endregion Khai bao bien local
            try
            {
                #region Validation
                // Neu person code la 01 thi se khong co sibling
                if (strPerCd.Equals("01") && isSibling)
                {
                    intMinBroCd = -1;
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Minimum Brother Code By Person Code: ", "Can not get minimum brother code of root father");
                }
                #endregion Validation
                dacConnMgr.OpenConnection();
                dacConnMgr.BeginTransaction();
                dacCmdMgr = new DACCommandManager();
                daoPerson = new DAOPerson() { person_code = strPerCd };
                if (lsPerson == null)
                {
                    if (isSibling)
                    {
                        strSqlQuery = STR_GET_MIN_SIBLING_CODE_BY_CUR_CODE;
                    }
                    else
                    {
                        strSqlQuery = STR_GET_MIN_DESCENDENT_CODE_BY_CUR_CODE;
                    }
                    strMsg = dacCmdMgr.ExecuteScalarCommand<DAOPerson>(daoPerson, dacConnMgr, System.Data.CommandType.Text, out intMinBroCd, strSqlQuery);
                }
                else
                {
                    if (isSibling)
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(BLGenealogic.GetXFatherCdOfPersonCd(strPerCd, BLGenealogic.FindGenRankOfPerCd(strPerCd) - 1))).ToList();
                    }
                    else
                    {
                        lsPerTemp = lsPerson.Where(x => BLGenealogic.GetXFatherCdOfPersonCd(x.person_code, BLGenealogic.FindGenRankOfPerCd(x.person_code) - 1)
                                .Equals(strPerCd)).ToList();
                    }
                    if (lsPerTemp != null)
                    {
                        intMinBroCd = lsPerTemp.Min(y => Convert.ToInt32(y.person_code.Substring(y.person_code.Length - 4)));
                    }
                    else
                    {
                        intMinBroCd = 0;
                    }
                    strMsg = "Successful";
                }
                if (intMinBroCd == -1)
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Min Brother Code By Person Code: ", strMsg);
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Person Manager - Get Min Brother Code By Person Code: ", strMsg);
            }
            catch (Exception ex)
            {
                intMinBroCd = -1;
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Person Manager - Get Min Brother Code By Person Code: ", ex.Message);
            }
        }
        #endregion GET MAX BROTHER(SIBLING)
        public string GenerateCodeFromPerson(ref DAOPerson daoNewPerson, int intCurPerId, bool isSibling, bool isYounger, int intMomCd, int intBroRank)
        {
            #region Declare variables
            string strDadCd = null;
            string strMomCd = null;
            string strBroCdFromCurr = null;
            int intBroCdFromCurr = 0;
            string strBroCdNew = null;
            string strMsgNotify = null;
            int intMaxBroCd = 0;
            int intMaxMomCd = 0;
            int intMinBroCd = 0;
            int intMinMomCd = 0;
            bool isOk = false;
            int intCase = 0;
            StringBuilder strBuilder = null;
            DACCommandManager dacCmdMgr = null;
            DAOPerson daoCurPer = null;
            List<DAOPerson> lsPerson = null;
            List<DAOPerson> lsBro = null;
            Dictionary<string, DAOPerson> dicPerForUpdate = null;
            #endregion Declare varibles
            try
            {
                #region Validation
                // Get all list person
                strMsgNotify = ListPerson(out lsPerson);
                if (lsPerson == null || (lsPerson != null && lsPerson.Count == 0))
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Member Management: ", "List Of Member Is Empty: " + strMsgNotify);
                }
                if (intCurPerId == 0) 
                {
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Member Management: ", "Need choose whom you will be begun from");
                }
                strMsgNotify = DetailPerson(intCurPerId, out daoCurPer);
                if (daoCurPer == null)
                {
                    return strMsgNotify;
                }
                #endregion Validation
                #region LOGIC GIAI QUYET BAI TOAN
                // Kiem tra lai thong tin ve mother. 
                // Case 1: mom code la new va lon nhat, khong phai gen lai ma chi insert
                // Case 2: mom code la new va nho nhat, phai gen lai bat dau tu mom code vua insert, brother code la 1
                // Case 3: mom code la old, gen lai bat dau tu brother code vua insert
                #endregion LOGIC GIAI QUYET BAI TOAN
                #region Sibling case
                if (isSibling)
                {
                    // Lay father code
                    strDadCd = BLGenealogic.GetXFatherCdOfPersonCd(daoCurPer.person_code, 1);
                    #region Generate mom code
                    // Re-Generate mom code
                    strMomCd = intMomCd.ToString("D3");
                    // Check existence of mom code
                    strMsgNotify = GetMaxMomCdByPerCd(daoCurPer.person_code, out intMaxMomCd, isSibling, lsPerson);
                    if (intMaxMomCd == -1)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Max Mother Sibling Code By Person Code: ", strMsgNotify);
                    }
                    strMsgNotify = GetMinMomCdByPerCd(daoCurPer.person_code, out intMinMomCd, isSibling, lsPerson);
                    if (intMinMomCd == -1)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Min Mother Sibling Code By Person Code: ", strMsgNotify);
                    }
                    // Case 1
                    if (intMomCd > intMaxMomCd)
                    {
                        intCase = 1;
                    }
                    // Case 2
                    else if (intMinMomCd == intMomCd)
                    {
                        intCase = 2;
                    }
                    // Case 3
                    else
                    {
                        intCase = 3;
                    }
                    #endregion Generate mom code
                    
                    #region Generate brother code
                    switch (intCase)
                    {
                        case 1:
                            {
                                strMsgNotify = GetMaxBroCdByPerCd(daoCurPer.person_code, out intMaxBroCd, isSibling, lsPerson);
                                if (intMaxBroCd == -1)
                                {
                                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Max Brother Sibling Code By Person Code: ", strMsgNotify);
                                }
                                strBroCdNew = (intMaxBroCd + 1).ToString("D3");
                                break;
                            }
                        case 2:
                            {
                                strMsgNotify = GetMinBroCdByPerCd(daoCurPer.person_code, out intMinBroCd, isSibling, lsPerson);
                                if (intMinBroCd == -1)
                                {
                                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Min Brother Sibling Code By Person Code: ", strMsgNotify);
                                }
                                strBroCdNew = intMinBroCd.ToString("D3");
                                break;
                            }
                        case 3:
                            {
                                // Lay brother rank tu nguoi hien tai
                                strBroCdFromCurr = daoCurPer.person_code.Substring(daoCurPer.person_code.Length - 4);
                                intBroCdFromCurr = Convert.ToInt32(strBroCdFromCurr);
                                // Neu them nguoi em, thi push cac nguoi em phia sau lui len 1. Vi du: 2,[3],insert here,4,5,6 => 2,3,[4],(4+1),(5+1),(6+1)
                                if (isYounger)
                                {
                                    strBroCdNew = (intBroCdFromCurr + 1).ToString("D3");
                                }
                                // Neu them nguoi anh, thi push tu nguoi hien tai lui ve sau 1. Vi du: 2,insert here,[3],4,5 => 2,[3],(3+1),(4+1),(5+1)
                                else
                                {
                                    strBroCdNew = intBroCdFromCurr.ToString("D3");
                                }
                                break;
                            }
                    }
                    #endregion Generate brother code

                    #region Re Generate all code after the code has just been changed
                    strBuilder = new StringBuilder().Append(strDadCd).Append(strMomCd).Append(strBroCdNew);
                    daoNewPerson.person_code = strBuilder.ToString();
                    if (intCase == 2 || intCase == 3)
                    {
                        lsPerson.Add(daoNewPerson);
                        isOk = ReGenPerCdFromMBCd(daoNewPerson, lsPerson, out dicPerForUpdate, intCase);
                    }
                    else
                    {
                        dicPerForUpdate = new Dictionary<string, DAOPerson>();
                        dicPerForUpdate.Add(strBuilder.ToString(), daoNewPerson);
                        isOk = true;
                    }
                    if (!isOk)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Member Management: ", "Re Generate It's Sibling Code And Descendent Code Unsuccesfully");
                    }
                    // Update and insert all changes

                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Member Management: ", "Generate Person Code Successfully");
                    #endregion Re Generate all code after the code has just been changed
                }
                #endregion Sibling case
                #region Descendent case
                else
                {
                    // Case: Them nguoi con
                    strDadCd = daoCurPer.person_code;
                    #region Generate mom code
                    strMsgNotify = GetMaxMomCdByPerCd(daoCurPer.person_code, out intMaxMomCd, isSibling, lsPerson);
                    if (intMaxMomCd == -1)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Max Mom Code By Descendent Of Person Code: ", strMsgNotify);
                    }
                    // Re-Generate mom code
                    strMomCd = intMomCd.ToString("D3");
                    strMsgNotify = GetMinMomCdByPerCd(daoCurPer.person_code, out intMinMomCd, isSibling, lsPerson);
                    if (intMinMomCd == -1)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Min Mother Code By Descendent Of Person Code: ", strMsgNotify);
                    }
                    // Case 1
                    if (intMomCd > intMaxMomCd)
                    {
                        intCase = 1;
                    }
                    // Case 2
                    else if (intMinMomCd == intMomCd)
                    {
                        intCase = 2;
                    }
                    // Case 3
                    else
                    {
                        intCase = 3;
                    }
                    #endregion Generate mom code
                    #region Generate brother code
                    switch (intCase)
                    {
                        case 1:
                            {
                                strMsgNotify = GetMaxBroCdByPerCd(daoCurPer.person_code, out intMaxBroCd, isSibling, lsPerson);
                                if (intMaxBroCd == -1)
                                {
                                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Max Brother Sibling Code By Person Code: ", strMsgNotify);
                                }
                                strBroCdNew = (intMaxBroCd + 1).ToString("D3");
                                break;
                            }
                        case 2:
                            {
                                strMsgNotify = GetMinBroCdByPerCd(daoCurPer.person_code, out intMinBroCd, isSibling, lsPerson);
                                if (intMinBroCd == -1)
                                {
                                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Member Management - Get Min Brother Sibling Code By Person Code: ", strMsgNotify);
                                }
                                strBroCdNew = intMinBroCd.ToString("D3");
                                break;
                            }
                        case 3:
                            {
                                // CAN CHECK LAI TRUONG HOP NAY: SE LOAD DATA LEN VIEW TRUOC - DROP DOWN LIST HIEN THI MIN, BROTHER RANK LIST, MAX, MIN, MOM CODE LIST, MAX
                                // Bat buoc end user phai cung cap thu tu anh em: intBroRank
                                // Check thu tu anh em co ton tai chua
                                daoNewPerson = lsPerson.Find(x => Convert.ToInt32(x.person_code.Substring(x.person_code.Length - 4)) == intBroRank);
                                // Lay brother rank tu nguoi cha
                                lsBro = lsPerson.FindAll(x => BLGenealogic.IsXDescendant(daoCurPer.person_code, x.person_code, BLGenealogic.FindGenRankOfPerCd(daoCurPer.person_code) + 1));
                                if (lsBro != null && lsBro.Count > 0)
                                {
                                    strBroCdFromCurr = lsBro.OrderByDescending(x => Convert.ToInt32(x.person_code.Substring(x.person_code.Length - 4))).First().person_code;
                                    strBroCdFromCurr = strBroCdFromCurr.Substring(strBroCdFromCurr.Length - 4);
                                    intBroCdFromCurr = Convert.ToInt32(strBroCdFromCurr);
                                }
                                else
                                {
                                    intBroCdFromCurr = 0;
                                }
                                // Neu them nguoi em, thi push cac nguoi em phia sau lui len 1. Vi du: 2,[3],insert here,4,5,6 => 2,3,[4],(4+1),(5+1),(6+1)
                                if (isYounger)
                                {
                                    strBroCdNew = (intBroCdFromCurr + 1).ToString("D3");
                                }
                                // Neu them nguoi anh, thi push tu nguoi hien tai lui ve sau 1. Vi du: 2,insert here,[3],4,5 => 2,[3],(3+1),(4+1),(5+1)
                                else
                                {
                                    strBroCdNew = (intBroCdFromCurr == 0 ? intBroCdFromCurr + 1 : intBroCdFromCurr).ToString("D3");
                                }
                                break;
                            }
                    }
                    #endregion Generate brother code
                    #region Re Generate all code after the code has just been changed
                    strBuilder = new StringBuilder().Append(strDadCd).Append(strMomCd).Append(strBroCdNew);
                    daoNewPerson.person_code = strBuilder.ToString();
                    if (intCase == 2 && intCase == 3)
                    {
                        lsPerson.Add(daoNewPerson);
                        isOk = ReGenPerCdFromMBCd(daoNewPerson, lsPerson, out dicPerForUpdate, intCase);
                    }
                    else
                    {
                        dicPerForUpdate = new Dictionary<string, DAOPerson>();
                        dicPerForUpdate.Add(strBuilder.ToString(), daoNewPerson);
                        isOk = true;
                    }
                    if (!isOk)
                    {
                        return BLMessageNotifier.NotifyMessage(Constants.MessageType.Warning, "Member Management: ", "Re Generate It's Brother Code And Descendent Code Unsuccesfully");
                    }
                    // Update and insert all changes
                    return BLMessageNotifier.NotifyMessage(Constants.MessageType.Success, "Member Management: ", "Generate Person Code Successfully");
                    #endregion Re Generate all code after the code has just been changed
                }
                #endregion Descendent case
            }
            catch (Exception ex)
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.RollbackTransaction();
                }
                return BLMessageNotifier.NotifyMessage(Constants.MessageType.Error, "Get Max Code Person Unsuccesfully With Exception: ", ex.Message);
            }
            finally
            {
                if (dacConnMgr != null)
                {
                    dacConnMgr.CloseConnection();
                }
            }
        }

        public bool ReGenPerCdFromMBCd(DAOPerson daoNewPer, List<DAOPerson> lsDaoPerson, out Dictionary<string, DAOPerson> dicPerForUpdate, int intCase)
        {
            #region Declare variables
            int intCurrentGenRank = 0;
            int intCheckGenRank = 0;
            bool isOlderBro = false;
            bool isOk = false;
            string strCurrentFatherCd = null;
            string strFatherCdTemp = null;
            int intCurrentBroRank = 0;
            int intBroRankTemp = 0;
            int intCurrentMomCd = 0;
            int intMomCdTemp = 0;
            string strPerCdTemp = null;
            StringBuilder strPerCd = null;
            List<DAOPerson> lsTemp = null;
            #endregion Declare variables
            if (lsDaoPerson == null)
            {
                dicPerForUpdate = null;
                return isOk;
            }
            intCurrentGenRank = BLGenealogic.FindGenRankOfPerCd(daoNewPer.person_code);
            // Filter brothers and descendent of this person code
            dicPerForUpdate = new Dictionary<string, DAOPerson>();
            // gen lai bat dau tu current person code
            intCurrentBroRank = Convert.ToInt32(daoNewPer.person_code.Substring(daoNewPer.person_code.Length - 4));
            intCurrentGenRank = BLGenealogic.FindGenRankOfPerCd(daoNewPer.person_code);
            strCurrentFatherCd = BLGenealogic.GetXFatherCdOfPersonCd(daoNewPer.person_code, intCurrentGenRank - 1);
            intCurrentMomCd = Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(daoNewPer.person_code));
            #region LOGIC GIAI QUYET BAI TOAN
            // Kiem tra lai thong tin ve mother. 
            // Case 1 (khong phai gen lai nen khong nhac den trong method nay): mom code la new va lon nhat
            // Case 2: mom code la new va nho nhat, phai gen lai bat dau tu mom code vua insert, brother code la 1
            // Case 3: mom code la old, gen lai bat dau tu brother code vua insert
            #endregion LOGIC GIAI QUYET BAI TOAN
            foreach (DAOPerson person in lsDaoPerson)
            {
                strPerCdTemp = person.person_code;
                intCheckGenRank = BLGenealogic.FindGenRankOfPerCd(strPerCdTemp);
                intBroRankTemp = Convert.ToInt32(strPerCdTemp.Substring(strPerCdTemp.Length - 4));
                strFatherCdTemp = BLGenealogic.GetXFatherCdOfPersonCd(strPerCdTemp, intCheckGenRank - 1);
                intMomCdTemp = Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(strPerCdTemp));
                isOlderBro = BLGenealogic.CheckIsBrother(daoNewPer.person_code, person.person_code, false, false, Constants.KindOfBrother.sibling);
                // Check this is the current person ? gen lai code bat dau tu nguoi nay
                if (intCurrentGenRank == intCheckGenRank && strCurrentFatherCd.Equals(strFatherCdTemp))
                {
                    // Check input mom code is duplicate ? gen lai mom code (tang len 1)
                    if (intCurrentMomCd == intMomCdTemp)
                    {
                        intMomCdTemp = intMomCdTemp + 1;
                        // Can re gen mem code cho cac mom code sau
                    }
                    strPerCd = new StringBuilder();
                    if (intCurrentBroRank == intBroRankTemp)
                    {
                        strPerCd.Append(strFatherCdTemp).Append(intMomCdTemp.ToString("D3")).Append((intBroRankTemp + 1).ToString("D3"));
                        person.person_code = strPerCd.ToString();
                        dicPerForUpdate.Add(daoNewPer.person_code, person);
                        lsTemp = new List<DAOPerson>();
                        lsDaoPerson.CopyTo(lsTemp.ToArray());
                        lsTemp.Remove(person);
                        RecursiveDescendentOfPerson(daoNewPer.person_code, lsTemp, dicPerForUpdate);
                    }
                    else if (isOlderBro)
                    {
                        strPerCd.Append(strFatherCdTemp).Append(intMomCdTemp.ToString("D3")).Append((intBroRankTemp + 1).ToString("D3"));
                        person.person_code = strPerCd.ToString();
                        dicPerForUpdate.Add(strPerCdTemp, person);
                        lsTemp = new List<DAOPerson>();
                        lsDaoPerson.CopyTo(lsTemp.ToArray());
                        lsTemp.Remove(person);
                        RecursiveDescendentOfPerson(strPerCdTemp, lsDaoPerson, dicPerForUpdate);
                    }
                }
            }
            isOk = true;
            return isOk;
        }
        private Dictionary<string,DAOPerson> RecursiveDescendentOfPerson(string strPerCd, List<DAOPerson> lsDaoPer, Dictionary<string, DAOPerson> dicDaoPerForUpdate)
        {
            #region Declare variables
            string strPerCdTemp = null;
            int intBroRankTemp = 0;
            string strCurrentFatherCd = null;
            //string strFatherCdTemp = null;
            int intMomCdTemp = 0;
            //int intCurrentBroRank = 0;
            int intCurrentGenRank = 0;
            //int intCheckGenRank = 0;
            //int intCurrentMomCd = 0;
            StringBuilder strBuilder = null;
            List<DAOPerson> lsTemp = null;
            #endregion Declare variables
            if (lsDaoPer == null)
            {
                return dicDaoPerForUpdate;
            }
            //intCurrentBroRank = Convert.ToInt32(strPerCd.Substring(strPerCd.Length - 4));
            intCurrentGenRank = BLGenealogic.FindGenRankOfPerCd(strPerCd);
            strCurrentFatherCd = BLGenealogic.GetXFatherCdOfPersonCd(strPerCd, intCurrentGenRank - 1);
            //intCurrentMomCd = Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(strPerCd));
            foreach (DAOPerson person in lsDaoPer)
            {
                strPerCdTemp = person.person_code;
                //intCheckGenRank = BLGenealogic.FindGenRankOfPerCd(strPerCdTemp);
                intBroRankTemp = Convert.ToInt32(strPerCdTemp.Substring(strPerCdTemp.Length - 4));
                //strFatherCdTemp = BLGenealogic.GetXFatherCdOfPersonCd(strPerCdTemp, intCheckGenRank - 1);
                intMomCdTemp = Convert.ToInt32(BLGenealogic.GetMotherCdOfPersonCd(strPerCdTemp));
                if (BLGenealogic.IsXDescendant(strPerCd, person.person_code, 1))
                {
                    if (!dicDaoPerForUpdate.ContainsKey(strPerCd))
                    {
                        strBuilder = new StringBuilder();
                        strBuilder.Append(strCurrentFatherCd).Append(intMomCdTemp.ToString("D3")).Append(intBroRankTemp.ToString("D3"));
                        person.person_code = strBuilder.ToString();
                        dicDaoPerForUpdate.Add(strPerCd, person);
                    }
                    lsTemp = new List<DAOPerson>();
                    lsDaoPer.CopyTo(lsTemp.ToArray());
                    lsTemp.Remove(person);
                    return RecursiveDescendentOfPerson(person.person_code, lsTemp, dicDaoPerForUpdate);
                }
            }
            return dicDaoPerForUpdate;
        }
        #endregion THEM MEMBER VAO GIA PHA
    }
    
}
